package com.orionlily.redis3t.throught;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.orionlily.redis3t.config.RedisConfig;
import com.orionlily.redis3t.entity.User;
import com.orionlily.redis3t.service.UserService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 缓存穿透(数据库不存在它)
 *
 * 正常情况下，我们去查询数据都是存在。
 *
 * 那么请求去查询一条压根儿数据库中根本就不存在的数据，也就是缓存和数据库都查询不到这条数据，但是请求每次都会打到数据库上面去。
 *
 * 这种查询不存在数据的现象我们称为缓存穿透。
 *
 *
 * @author li.lc
 */
@RequestMapping("/throught")
@RestController
public class ThroughtController {

    @Resource(name = "userService")
    private UserService userService;

    @Resource(name = "bloomFilterHelper")
    private BloomFilterHelper bloomFilterHelper;

    @Resource(name = "redisBloomFilter")
    private RedisBloomFilter redisBloomFilter;

    @Resource(name = "redisTemplate")
    private RedisTemplate redisTemplate;

    private static final String bloomFilterKey = "id_exist_bloom";

    @GetMapping("/{id}")
    public String getData(@PathVariable Long id) throws JsonProcessingException {
        boolean idInBloom = redisBloomFilter.includeByBloomFilter(bloomFilterHelper, bloomFilterKey, id.toString());
        if (!idInBloom) {
            return "该id不在bloomFilter";
        }

        Object value = redisTemplate.opsForValue().get("llc" + id.toString());
        if (Objects.nonNull(value)) {
            return "在缓存查询到id=" + id + "的值=" + value.toString();
        }

        User user = userService.queryById(id);
        if (Objects.nonNull(user)) {
            redisTemplate.opsForValue().set("llc" + id.toString(), user, 30, TimeUnit.MINUTES);
            return "在数据库查询到id=" + id + "的值=" + user;
        } else {
            redisTemplate.opsForValue().set("llc" + id.toString(), null, 30, TimeUnit.SECONDS);
            return "在数据库没id=" + id + "的值，缓存空到redis";
        }
    }

    @PostMapping()
    public String addData(@RequestBody User user) {
        userService.insert(user);
        redisBloomFilter.addByBloomFilter(bloomFilterHelper, bloomFilterKey, user.getId().toString());
        return user.getId() > 0 ? "success" : "fail";
    }

    @PutMapping()
    public String updateData(User user) {
        return userService.update(user) ? "success" : "fail";
    }

    @DeleteMapping("/{id}")
    public String updateData(@PathVariable Long id) {
        return userService.deleteById(id) ? "success" : "fail";
    }

}
